﻿using MimeKit;
using MimeKit.Text;
using Zhp.Entity.Message.Email;
using Zhp.IService.Message.Email;
using Zhp.SqlSugar.Repository;

namespace Zhp.Service.Message.Email
{
    public class EmailSender : IEmailSender
    {
        private readonly ISmtpBuilder _smtpBuilder;
        private readonly IBaseRepository<EmailAccount> _emailAccountRep;
        private readonly IBaseRepository<EmailTemplate> _emailTemplateRep;
        private readonly IEmailTemplateRender _emailTemplateRender;
        public EmailSender(ISmtpBuilder smtpBuilder, IBaseRepository<EmailAccount> emailAccountRep, IBaseRepository<EmailTemplate> emailTemplateRep, IEmailTemplateRender emailTemplateRender)
        {
            _smtpBuilder = smtpBuilder;
            _emailAccountRep = emailAccountRep;
            _emailTemplateRep = emailTemplateRep;
            _emailTemplateRender = emailTemplateRender;
        }

        public async Task<bool> SendEmailAsync(string tplName, object emailData, string toAddress, string toName, string replyToAddress = null, string replyToName = null, IEnumerable<string> bcc = null, IEnumerable<string> cc = null, string attachmentFilePath = null, string attachmentFileName = null, int attachedDownloadId = 0, IDictionary<string, string> headers = null)
        {
            var tpl = await _emailTemplateRep.GetFirstAsync(x => x.Name == tplName && x.IsActive);
            if (tpl == null)
            {
                throw new Exception($"模板{tplName}不存在!");
            }
            var account = await _emailAccountRep.GetByIdAsync(tpl.EmailAccountId);
            if (account == null)
            {
                throw new Exception($"模板选择的账户不存在!");
            }
            if (string.IsNullOrEmpty(toAddress))
            {
                throw new Exception($"收件人邮箱地址不能为空!");
            }
            tpl = await _emailTemplateRender.RenderTemplateAsync(tpl, emailData);

            var ret = await SendEmailAsync(account, tpl.Subject, tpl.Body, toAddress, toName, replyToAddress, replyToName, bcc, cc, attachmentFilePath, attachmentFileName, attachedDownloadId, headers);

            return ret;
        }

        public async Task<bool> SendEmailAsync(EmailAccount emailAccount, string subject, string body, string toAddress, string toName, string replyToAddress = null, string replyToName = null, IEnumerable<string> bcc = null, IEnumerable<string> cc = null, string attachmentFilePath = null, string attachmentFileName = null, int attachedDownloadId = 0, IDictionary<string, string> headers = null)
        {
            var message = new MimeMessage();

            message.From.Add(new MailboxAddress(emailAccount.DisplayName, emailAccount.Email));
            message.To.Add(new MailboxAddress(toName, toAddress));

            if (!string.IsNullOrEmpty(replyToAddress))
            {
                message.ReplyTo.Add(new MailboxAddress(replyToName, replyToAddress));
            }

            //BCC
            if (bcc != null)
            {
                foreach (var address in bcc.Where(bccValue => !string.IsNullOrWhiteSpace(bccValue)))
                {
                    message.Bcc.Add(new MailboxAddress("", address.Trim()));
                }
            }

            //CC
            if (cc != null)
            {
                foreach (var address in cc.Where(ccValue => !string.IsNullOrWhiteSpace(ccValue)))
                {
                    message.Cc.Add(new MailboxAddress("", address.Trim()));
                }
            }

            //content
            message.Subject = subject;

            //headers
            if (headers != null)
            {
                foreach (var header in headers)
                {
                    message.Headers.Add(header.Key, header.Value);
                }
            }

            var multipart = new Multipart("mixed")
            {
                new TextPart(TextFormat.Html) { Text = body }
            };
            message.Body = multipart;

            //send email
            using var smtpClient = await _smtpBuilder.BuildAsync(emailAccount);
            var result = await smtpClient.SendAsync(message);
            await smtpClient.DisconnectAsync(true);
            return result != null && result.Contains("OK", StringComparison.CurrentCultureIgnoreCase);
        }
    }
}
